package com.jymj.common.config;

import com.jymj.common.filter.AuthenticationValidateFilter;
import com.jymj.common.shiro.UserRealm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.web.filter.DelegatingFilterProxy;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * shiro相关配置
 *
 * @author haosai
 */
@Configuration
public class ShiroConfig {

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        DelegatingFilterProxy proxy = new DelegatingFilterProxy();
        proxy.setTargetFilterLifecycle(true);
        proxy.setTargetBeanName("shiroFilter");
        filterRegistrationBean.setFilter(proxy);
        filterRegistrationBean.addUrlPatterns("/*");
        return filterRegistrationBean;
    }

    /**
     * LifecycleBeanPostProcessor，这是个DestructionAwareBeanPostProcessor的子类，
     * 负责org.apache.shiro.util.Initializable类型bean的生命周期的，初始化和销毁。 主要是AuthorizingRealm类的子类，以及EhCacheManager类。
     *
     * @return LifecycleBeanPostProcessor
     */
    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * ShiroFilterFactoryBean，是个factorybean，为了生成ShiroFilter。
     *
     * @return ShiroFilterFactoryBean
     */
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilterFactoryBean() {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        shiroFilterFactoryBean.setLoginUrl("/login.html");
        shiroFilterFactoryBean.setSuccessUrl("/map_pc.jsp");
        shiroFilterFactoryBean.setUnauthorizedUrl("/");
        Map<String, Filter> map = new HashMap<>();
        map.put("acf", new AuthenticationValidateFilter());
        shiroFilterFactoryBean.setFilters(map);
        Map<String, String> filterChainDefinitionManager = new LinkedHashMap<>();

        //放行Swagger接口
        filterChainDefinitionManager.put("/swagger-ui.html","anon");
        filterChainDefinitionManager.put("/swagger/**","anon");
        filterChainDefinitionManager.put("/webjars/**","anon");
        filterChainDefinitionManager.put("/swagger-resources/**","anon");
        filterChainDefinitionManager.put("/v2/**","anon");
        filterChainDefinitionManager.put("/configuration/security", "anon");
        filterChainDefinitionManager.put("/configuration/ui", "anon");
        filterChainDefinitionManager.put("/doc.html","anon");

        filterChainDefinitionManager.put("/andrVersion/**", "anon");
        filterChainDefinitionManager.put("/enviorFile/**", "anon");
        filterChainDefinitionManager.put("/expect/**", "anon");
        filterChainDefinitionManager.put("/taskChildFile/**", "anon");
        filterChainDefinitionManager.put("/basegh/**", "anon");
        filterChainDefinitionManager.put("/contract/**", "anon");
        filterChainDefinitionManager.put("/meetSummry/**", "anon");
        filterChainDefinitionManager.put("/progress/**", "anon");
        filterChainDefinitionManager.put("/checkpicture/**", "anon");
        filterChainDefinitionManager.put("/checkdata/**", "anon");
        filterChainDefinitionManager.put("/api/**", "anon");
        filterChainDefinitionManager.put("/IllegalFile/**", "anon");
        filterChainDefinitionManager.put("/complaintFile/**", "anon");
        filterChainDefinitionManager.put("/zjdSqFile/**", "anon");
        filterChainDefinitionManager.put("/zjdlzfile/**", "anon");
        filterChainDefinitionManager.put("/zjdTcFile/**", "anon");
        filterChainDefinitionManager.put("/applyFile/**", "anon");
        filterChainDefinitionManager.put("/enviorFile/**", "anon");
        filterChainDefinitionManager.put("/RenovatedFile/**", "anon");
        filterChainDefinitionManager.put("/PointRecord/**", "anon");
        filterChainDefinitionManager.put("/login.html", "anon");
        filterChainDefinitionManager.put("/backstage.html", "anon");
        filterChainDefinitionManager.put("/statics/**", "anon");
        filterChainDefinitionManager.put("/sys/backstage", "anon");
        filterChainDefinitionManager.put("/version/**", "anon");
        filterChainDefinitionManager.put("/zipFile/**", "anon");
        filterChainDefinitionManager.put("/monthZipFile/**", "anon");
        filterChainDefinitionManager.put("/excel/**", "anon");
        filterChainDefinitionManager.put("/sys/getKaptcha", "anon");
        filterChainDefinitionManager.put("**/copyFile.zip", "anon");
        filterChainDefinitionManager.put("/**/queryAllPic", "anon");
        filterChainDefinitionManager.put("/**/queryPicByMonth", "anon");
        filterChainDefinitionManager.put("/sys/user/restpassword", "anon");
        filterChainDefinitionManager.put("/captcha.jpg", "anon");
        filterChainDefinitionManager.put("/sys/login", "anon");
        filterChainDefinitionManager.put("/sys/applogin", "anon");
        filterChainDefinitionManager.put("/sys/authBymobile", "anon");
        filterChainDefinitionManager.put("/sys/getCode", "anon");
        //用户为ROLE_USER 角色可以访问。由用户角色控制用户行为。
        //filterChainDefinitionManager.put("/user/**", "authc,roles[ROLE_USER]");
        //filterChainDefinitionManager.put("/events/**", "authc,roles[ROLE_ADMIN]");
        // 这里为了测试，固定写死的值，也可以从数据库或其他配置中读取，此处是用权限控制
        //filterChainDefinitionManager.put("/user/edit/**", "authc,perms[user:edit]");
        filterChainDefinitionManager.put("/**", "acf");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionManager);
        return shiroFilterFactoryBean;
    }

    /**
     * DefaultAdvisorAutoProxyCreator，Spring的一个bean，由Advisor决定对哪些类的方法进行AOP代理。
     *
     * @return DefaultAdvisorAutoProxyCreator
     */
    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    //@ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
        defaultAAP.setProxyTargetClass(true);
        return defaultAAP;
    }

    /**
     * AuthorizationAttributeSourceAdvisor，shiro里实现的Advisor类，
     * 内部使用AopAllianceAnnotationsAuthorizingMethodInterceptor来拦截用以下注解的方法。
     *
     * @return AuthorizationAttributeSourceAdvisor
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor aASA = new AuthorizationAttributeSourceAdvisor();
        aASA.setSecurityManager(securityManager());
        return aASA;
    }

    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //设置realm.
        //securityManager.setSessionManager(defaultWebSessionManager());
        //securityManager.setAuthenticator(customizedModularRealmAuthenticator());
        //List<Realm> realms = new ArrayList<>();
        //realms.add(userRealm());
        securityManager.setRealm(userRealm());

        return securityManager;
    }

    @Bean
    public DefaultWebSessionManager defaultWebSessionManager() {
        DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager();
        defaultWebSessionManager.setGlobalSessionTimeout(3600000);
        defaultWebSessionManager.setSessionValidationSchedulerEnabled(true);
        return defaultWebSessionManager;
    }

    @Bean
    public UserRealm userRealm() {
        UserRealm myShiroRealm = new UserRealm();
        return myShiroRealm;
    }

    @Bean
    public AuthenticationValidateFilter authenticationValidateFilter() {
        AuthenticationValidateFilter authenticationValidateFilter = new AuthenticationValidateFilter();
        return authenticationValidateFilter;
    }

}
